﻿//
// XN4SL - Xna Framework for Silverlight.
//
using System;

namespace Xn4Sl.Framework
{
    /// <summary>
    /// Defines a vector with two components.
    /// </summary>
    public struct Vector2 : IEquatable<Vector2>
    {
        /// <summary>
        /// Gets or sets the x-component of the vector.
        /// </summary>
        private float x;
        public float X
        {
            get
            {
                return this.x;
            }
            set
            {
                this.x = value;
            }
        }
        /// <summary>
        /// Gets or sets the y-component of the vector.
        /// </summary>
        private float y;
        public float Y
        {
            get
            {
                return this.y;
            }
            set
            {
                this.y = value;
            }
        }
        /// <summary>
        /// Creates a new instance of Vector2.
        /// </summary>
        /// <param name="value">Value to initialize both components to.</param>
        public Vector2(float value) 
        {
            this.x = this.y = value;
        }
        /// <summary>
        /// Initializes a new instance of Vector2.
        /// </summary>
        /// <param name="x">Initial value for the x-component of the vector.</param>
        /// <param name="y">Initial value for the y-component of the vector.</param>
        public Vector2(float x, float y) 
        {
            this.x = x;
            this.y = y;
        }
        /// <summary>
        /// Initializes a new instance of Vector2.
        /// </summary>
        /// <param name="x">Initial value for the x-component of the vector.</param>
        /// <param name="y">Initial value for the y-component of the vector.</param>
        public Vector2(double x, double y)
        {
            this.x = (float)x;
            this.y = (float)y;
        }
        /// <summary>
        /// Returns a vector pointing in the opposite direction.
        /// </summary>
        /// <param name="value">Source vector.</param>
        /// <returns>Vector pointing in the opposite direction.</returns>
        public static Vector2 operator -(Vector2 value) 
        {
            return new Vector2(-value.X, -value.Y);
        }
        /// <summary>
        /// Subtracts a vector from a vector.
        /// </summary>
        /// <param name="value1">Source vector.</param>
        /// <param name="value2">Source vector.</param>
        /// <returns>Result of the subtraction.</returns>
        public static Vector2 operator -(Vector2 value1, Vector2 value2)
        {
            return new Vector2(value1.X - value2.X, value1.Y - value2.Y);
        }
        /// <summary>
        /// Tests vectors for inequality.
        /// </summary>
        /// <param name="value1">Vector to compare.</param>
        /// <param name="value2">Vector to compare.</param>
        /// <returns>Returns true if the vectors are not equal, false otherwise.</returns>
        public static bool operator !=(Vector2 value1, Vector2 value2) 
        {
            return !(value1 == value2);
        }
        /// <summary>
        /// Multiplies a vector by a scalar value.
        /// </summary>
        /// <param name="scaleFactor">Scalar value.</param>
        /// <param name="value">Source vector.</param>
        /// <returns>Result of the multiplication.</returns>
        public static Vector2 operator *(float scaleFactor, Vector2 value) 
        {
            return new Vector2(value.X * scaleFactor, value.Y * scaleFactor);
        }
        /// <summary>
        /// Multiplies a vector by a scalar value.
        /// </summary>
        /// <param name="value">Source vector.</param>
        /// <param name="scaleFactor">Scalar value.</param>
        /// <returns>Result of the multiplication.</returns>
        public static Vector2 operator *(Vector2 value, float scaleFactor) 
        {
            return  scaleFactor * value;
        }
        /// <summary>
        /// Multiplies the components of two vectors by each other.
        /// </summary>
        /// <param name="value1">Source vector.</param>
        /// <param name="value2">Source vector.</param>
        /// <returns>Result of the multiplication.</returns>
        public static Vector2 operator *(Vector2 value1, Vector2 value2) 
        {
            return new Vector2(value1.X * value2.X, value1.Y * value2.Y);
        }
        /// <summary>
        /// Divides a vector by a scalar value.
        /// </summary>
        /// <param name="value1">Source vector.</param>
        /// <param name="divider">The divisor.</param>
        /// <returns>The source vector divided by a scalar value.</returns>
        public static Vector2 operator /(Vector2 value1, float divider) 
        {
            return new Vector2(value1.X / divider, value1.Y / divider);
        }    
        /// <summary>
        /// Divides the components of a vector by the components of another vector.
        /// </summary>
        /// <param name="value1">Source vector.</param>
        /// <param name="value2">Divisor vector.</param>
        /// <returns>The result of dividing the vectors.</returns>
        public static Vector2 operator /(Vector2 value1, Vector2 value2)
        {
            return new Vector2(value1.X / value2.X, value1.Y / value2.Y);
        }
        /// <summary>
        /// Adds two vectors.
        /// </summary>
        /// <param name="value1">Source vector.</param>
        /// <param name="value2">Source vector.</param>
        /// <returns>Sum of the source vectors.</returns>
        public static Vector2 operator +(Vector2 value1, Vector2 value2) 
        {
            return new Vector2(value1.X + value2.X, value1.Y + value2.Y);
        }
        /// <summary>
        /// Tests vectors for equality.
        /// </summary>
        /// <param name="value1">Source vector.</param>
        /// <param name="value2">Source vector.</param>
        /// <returns>true if the vectors are equal; false otherwise.</returns>
        public static bool operator ==(Vector2 value1, Vector2 value2)
        {
            // TODO: implement
            return value1.X == value2.X && value1.Y == value2.Y;
        }
        /// <summary>
        /// Returns a Vector2 with both of its components set to one.
        /// </summary>
        public static Vector2 One 
        { 
            get 
            { 
                return new Vector2(1, 1);
            } 
        }
        /// <summary>
        /// Returns the unit vector for the x-axis.
        /// </summary>
        public static Vector2 UnitX 
        {
            get
            {
                return new Vector2(1, 0);
            }
        }
        /// <summary>
        /// Returns the unit vector for the y-axis.
        /// </summary>
        public static Vector2 UnitY
        {
            get
            {
                return new Vector2(0, 1);
            }
        }
        /// <summary>
        /// Returns a Vector2 with all of its components set to zero.
        /// </summary>
        public static Vector2 Zero
        {
            get
            {
                return new Vector2(0, 0);
            }
        }
        /// <summary>
        /// Adds two vectors.
        /// </summary>
        /// <param name="value1">Source vector.</param>
        /// <param name="value2">Source vector.</param>
        /// <returns>Sum of the source vectors.</returns>
        public static Vector2 Add(Vector2 value1, Vector2 value2) 
        { 
            return value1 + value2; 
        }
        /// <summary>
        /// Adds two vectors.
        /// </summary>
        /// <param name="value1">Source vector.</param>
        /// <param name="value2">Source vector.</param>
        /// <param name="result">Sum of the source vectors.</param>
        public static void Add(ref Vector2 value1, ref Vector2 value2, out Vector2 result)
        {
            result = value1 + value2;
        }
        /// <summary>
        /// Returns a value that indicates whether the current instance is equal to a specified object.
        /// </summary>
        /// <param name="obj">Object to make the comparison with.</param>
        /// <returns>true if the current instance is equal to the specified object; false otherwise.</returns>
        public override bool Equals(object obj)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Determines whether the specified System.Object is equal to the Vector2.
        /// </summary>
        /// <param name="other">The System.Object to compare with the current Vector2.</param>
        /// <returns>true if the specified System.Object is equal to the current Vector2; 
        /// false otherwise.</returns>
        public bool Equals(Vector2 other)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Gets the hash code of the vector object.
        /// </summary>
        /// <returns>Hash code of the vector object.</returns>
        public override int GetHashCode()
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Calculates the length of the vector.
        /// </summary>
        /// <returns>Length of the vector.</returns>
        public float Length()
        {
            return (float)Math.Sqrt(this.LengthSquared());
        }
        /// <summary>
        /// Calculates the length of the vector squared.
        /// </summary>
        /// <returns>The length of the vector squared.</returns>
        public float LengthSquared()
        {
            return (float)(Math.Pow(this.x, 2) + Math.Pow(this.y, 2));
        }
        /// <summary>
        /// Returns a vector pointing in the opposite direction.
        /// </summary>
        /// <param name="value">Source vector.</param>
        /// <returns>Vector pointing in the opposite direction.</returns>
        public static Vector2 Negate(Vector2 value)
        {
            return new Vector2(-value.X, -value.Y);
        }
        /// <summary>
        /// Returns a vector pointing in the opposite direction.
        /// </summary>
        /// <param name="value">Source vector.</param>
        /// <param name="result">Vector pointing in the opposite direction.</param>
        public static void Negate(ref Vector2 value, out Vector2 result)
        {
            result = Vector2.Negate(value);
        }
        //
        // Summary:
        //     Retrieves a string representation of the current object.
        //
        // Returns:
        //     String that represents the object.
        public override string ToString()
        {
            return String.Format("{{X:{0},Y:{1}{2}", this.x, this.y, "}");
        }
    }
}
